/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.primecodegen.util;

/**
 *
 * @author Mohammad
 */
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import freemarker.core.Environment;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;

/**
 * @author kdu
 */
public final class FreeMarkerUtil {

    /**
     * private construction.
     */
    private FreeMarkerUtil() {
    }

    /**
     * get a configuration form freemarker.
     * @param templatePath path of template.
     * @return Configuration.
     */
    public static Configuration getConfig(final String templatePath) {
        Configuration config = new Configuration();
        try {
            config.setDirectoryForTemplateLoading(new File(templatePath));
        } catch (IOException e) {
            System.err.println("templatePath:"
                    + templatePath + " is not right.\n" + e.getMessage());
        }
        config.setObjectWrapper(new DefaultObjectWrapper());
        return config;
    }

    /**
     * get a template form freemarker.
     * @param config Configuration.
     * @param templateName name of template.
     * @param templateEncoding encoding of template.
     * @return Template.
     */
    public static Template getTemplate(final Configuration config,
            final String templateName, final String templateEncoding) {
        try {
            return config.getTemplate(templateName, templateEncoding);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * write out the data.
     * @param template Template.
     * @param root data mode.
     * @param out output stream.
     */
    public static void outPut(Template template, Map<?, ?> root,
            final Writer out) {
        try {
            template.process(root, out);
            out.flush();
            out.close();
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * process a freemarker template.
     * @param templatePath path of template
     * @param templateName name of template
     * @param templateEncoding encoding of template
     * @param root data mode
     * @param out output stream
     */
    public static void processTemplate(final String templatePath,
            final String templateName, final String templateEncoding,
            Map<?, ?> root, final Writer out) {
        Configuration config = getConfig(templatePath);
        Template template = getTemplate(config, templateName, templateEncoding);
        outPut(template, root, out);
    }

    /**
     * 将params的值复制到variable中
     * 
     * @param env
     * @param params
     * @return 原Variable中的值
     * @throws TemplateException
     */
    public static Map<String, TemplateModel> addParamsToVariable(
            Environment env, Map<String, TemplateModel> params)
            throws TemplateException {
        Map<String, TemplateModel> origMap = new HashMap<String, TemplateModel>();
        if (params.size() <= 0) {
            return origMap;
        }
        Set<Map.Entry<String, TemplateModel>> entrySet = params.entrySet();
        String key;
        TemplateModel value;
        for (Map.Entry<String, TemplateModel> entry : entrySet) {
            key = entry.getKey();
            value = env.getVariable(key);
            if (value != null) {
                origMap.put(key, value);
            }
            env.setVariable(key, entry.getValue());
        }
        return origMap;
    }

    /**
     * 将variable中的params值移除
     * 
     * @param env
     * @param params
     * @param origMap
     * @throws TemplateException
     */
    public static void removeParamsFromVariable(Environment env,
            Map<String, TemplateModel> params,
            Map<String, TemplateModel> origMap) throws TemplateException {
        if (params.size() <= 0) {
            return;
        }
        for (String key : params.keySet()) {
            env.setVariable(key, origMap.get(key));
        }
    }
}
